﻿using Furion.DatabaseAccessor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iemtm.WeChat.Core
{
    public class EntityBuff<Key, T> where T : class, IPrivateEntity, new()
    {
        protected Dictionary<Key, T> buff = new Dictionary<Key, T>();
        protected object lockObj = new object();

        public Dictionary<Key, T> All
        {
            get
            {
                Dictionary<Key, T> tmp = new Dictionary<Key, T>();
                lock (lockObj)
                {
                    if (buff != null)
                    {
                        IEnumerator en = buff.Keys.GetEnumerator();
                        while (en.MoveNext())
                        {
                            Key k = (Key)en.Current;
                            tmp.Add(k, buff[k]);
                        }
                    }
                }
                return tmp;
            }
            set
            {
                lock (lockObj)
                {
                    buff = value;
                }
            }
        }

        

        public string KeyName { get; set; }
        /// <summary>
        /// 不能用构造函数 必须指定key
        /// </summary>
        protected EntityBuff()
        {
           
        }
        public EntityBuff(string keyName)
        {
            this.KeyName = keyName;
        }

        /// <summary>
        /// 从数据库加载数据
        /// </summary>
        public void UpdateFromDB()
        {
            var entityRepository = Db.GetRepository<T>();

            List<T> ls = entityRepository.AsEnumerable();//.AsNoTracking().QueryList(q);
            if (ls == null || ls.Count <= 0)
                return;
            Dictionary<Key, T> tmp = new Dictionary<Key, T>();
            foreach (T en in ls)
            {
                Key keyValue = (Key)GetPropertiesValue(en, KeyName);
                if (keyValue != null&&!tmp.ContainsKey(keyValue))
                {
                    tmp.Add((Key)(keyValue), en);
                }
            }
            All = tmp;
        }

        public void Update(T en)
        {
            if (en == null)
                return;
            Key k = (Key)(GetPropertiesValue(en, KeyName));
            T enTmp = null;
            lock (lockObj)
            {
                if (buff.ContainsKey(k))
                    enTmp = buff[k];
                else
                    buff.Add(k, en);
            }
            if (enTmp != null)
            {
                CopyPdfEn(en, enTmp);
            }
        }
        public void Remove(IEnumerable<T> ls)
        {
            if (ls == null)
                return;
            lock (lockObj)
            {
                foreach (T en in ls)
                    if (en != null)
                    {
                        Key k = (Key)(GetPropertiesValue(en, KeyName));
                        if (buff.ContainsKey(k))
                            buff.Remove(k);
                    }
            }
        }

        public void Remove(IEnumerable<Key> keys)
        {
            if (keys == null)
                return;
            lock (lockObj)
            {
                foreach (Key k in keys)
                    if (k != null && buff.ContainsKey(k))
                        buff.Remove(k);
            }
        }

        public void Remove(Key k)
        {
            if (k == null)
                return;
            lock (lockObj)
            {
                if (buff.ContainsKey(k))
                    buff.Remove(k);
            }
        }

        public void Remove(T en)
        {
            if (en == null)
                return;
            lock (lockObj)
            {
                Key k = (Key)(GetPropertiesValue(en, KeyName));
                if (buff.ContainsKey(k))
                    buff.Remove(k);
            }
        }

        public T this[Key id]
        {
            get
            {
                T en = null;
                lock (lockObj)
                {
                    if (buff.ContainsKey(id))
                        en = buff[id];
                }
                return en;
            }
            set
            {
                Update(value);
            }
        }

        /// <summary>
        /// 根据属性名 获取 属性值
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="t"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        protected object GetPropertiesValue(T t,string key)
        {
            try
            {
                var Temp = t.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).FirstOrDefault(u => u.Name == key);
                if (Temp != null)
                    return Temp.GetValue(t, null);
                return null;
            }
            catch (Exception error)
            {
                return null;
            }
        }

        /// <summary>
        /// 将一个实体类复制到另一个实体类
        /// </summary>
        /// <param name="objectsrc">源实体类</param>
        /// <param name="objectdest">复制到的实体类</param>
        public static void CopyPdfEn(object objectsrc, object objectdest)
        {
            try
            {
                var sourceType = objectsrc.GetType();
                var destType = objectdest.GetType();
                foreach (var source in sourceType.GetProperties())
                {
                    foreach (var dest in destType.GetProperties())
                    {
                        if (dest.Name == source.Name)
                        {
                            dest.SetValue(objectdest, source.GetValue(objectsrc));
                        }
                    }
                }
            }
            catch (Exception error)
            {

            }
        }
    }
}
